home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / firefox / components / nsUrlClassifierTable.js < prev    next >
Encoding:
JavaScript  |  2007-04-03  |  44.8 KB  |  1,404 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is Url Classifier code
  15.  *
  16.  * The Initial Developer of the Original Code is
  17.  * Google Inc.
  18.  * Portions created by the Initial Developer are Copyright (C) 2006
  19.  * the Initial Developer. All Rights Reserved.
  20.  *
  21.  * Contributor(s):
  22.  *   Tony Chang <tony@ponderer.org>
  23.  *
  24.  * Alternatively, the contents of this file may be used under the terms of
  25.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  26.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27.  * in which case the provisions of the GPL or the LGPL are applicable instead
  28.  * of those above. If you wish to allow use of your version of this file only
  29.  * under the terms of either the GPL or the LGPL, and not to allow others to
  30.  * use your version of this file under the terms of the MPL, indicate your
  31.  * decision by deleting the provisions above and replace them with the notice
  32.  * and other provisions required by the GPL or the LGPL. If you do not delete
  33.  * the provisions above, a recipient may use your version of this file under
  34.  * the terms of any one of the MPL, the GPL or the LGPL.
  35.  *
  36.  * ***** END LICENSE BLOCK ***** */
  37.  
  38. const Cc = Components.classes;
  39. const Ci = Components.interfaces;
  40.  
  41. // js/lang.js is needed for Function.prototype.inherts
  42. /* ***** BEGIN LICENSE BLOCK *****
  43.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  44.  *
  45.  * The contents of this file are subject to the Mozilla Public License Version
  46.  * 1.1 (the "License"); you may not use this file except in compliance with
  47.  * the License. You may obtain a copy of the License at
  48.  * http://www.mozilla.org/MPL/
  49.  *
  50.  * Software distributed under the License is distributed on an "AS IS" basis,
  51.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  52.  * for the specific language governing rights and limitations under the
  53.  * License.
  54.  *
  55.  * The Original Code is Google Safe Browsing.
  56.  *
  57.  * The Initial Developer of the Original Code is Google Inc.
  58.  * Portions created by the Initial Developer are Copyright (C) 2006
  59.  * the Initial Developer. All Rights Reserved.
  60.  *
  61.  * Contributor(s):
  62.  *   Aaron Boodman <aa@google.com> (original author)
  63.  *
  64.  * Alternatively, the contents of this file may be used under the terms of
  65.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  66.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  67.  * in which case the provisions of the GPL or the LGPL are applicable instead
  68.  * of those above. If you wish to allow use of your version of this file only
  69.  * under the terms of either the GPL or the LGPL, and not to allow others to
  70.  * use your version of this file under the terms of the MPL, indicate your
  71.  * decision by deleting the provisions above and replace them with the notice
  72.  * and other provisions required by the GPL or the LGPL. If you do not delete
  73.  * the provisions above, a recipient may use your version of this file under
  74.  * the terms of any one of the MPL, the GPL or the LGPL.
  75.  *
  76.  * ***** END LICENSE BLOCK ***** */
  77.  
  78. // This file has pure js helper functions. Hence you'll find metion
  79. // of browser-specific features in here.
  80.  
  81.  
  82. /**
  83.  * lang.js - The missing JavaScript language features
  84.  *
  85.  * WARNING: This class adds members to the prototypes of String, Array, and
  86.  * Function for convenience.
  87.  *
  88.  * The tradeoff is that the for/in statement will not work properly for those
  89.  * objects when this library is used.
  90.  *
  91.  * To work around this for Arrays, you may want to use the forEach() method,
  92.  * which is more fun and easier to read.
  93.  */
  94.  
  95. /**
  96.  * Returns true if the specified value is |null|
  97.  */
  98. function isNull(val) {
  99.   return val === null;
  100. }
  101.  
  102. /**
  103.  * Returns true if the specified value is an array
  104.  */
  105. function isArray(val) {
  106.   return isObject(val) && val.constructor == Array;
  107. }
  108.  
  109. /**
  110.  * Returns true if the specified value is a string
  111.  */
  112. function isString(val) {
  113.   return typeof val == "string";
  114. }
  115.  
  116. /**
  117.  * Returns true if the specified value is a boolean
  118.  */
  119. function isBoolean(val) {
  120.   return typeof val == "boolean";
  121. }
  122.  
  123. /**
  124.  * Returns true if the specified value is a number
  125.  */
  126. function isNumber(val) {
  127.   return typeof val == "number";
  128. }
  129.  
  130. /**
  131.  * Returns true if the specified value is a function
  132.  */
  133. function isFunction(val) {
  134.   return typeof val == "function";
  135. }
  136.  
  137. /**
  138.  * Returns true if the specified value is an object
  139.  */
  140. function isObject(val) {
  141.   return val && typeof val == "object";
  142. }
  143.  
  144. /**
  145.  * Returns an array of all the properties defined on an object
  146.  */
  147. function getObjectProps(obj) {
  148.   var ret = [];
  149.  
  150.   for (var p in obj) {
  151.     ret.push(p);
  152.   }
  153.  
  154.   return ret;
  155. }
  156.  
  157. /**
  158.  * Returns true if the specified value is an object which has no properties
  159.  * defined.
  160.  */
  161. function isEmptyObject(val) {
  162.   if (!isObject(val)) {
  163.     return false;
  164.   }
  165.  
  166.   for (var p in val) {
  167.     return false;
  168.   }
  169.  
  170.   return true;
  171. }
  172.  
  173. var getHashCode;
  174. var removeHashCode;
  175.  
  176. (function () {
  177.   var hashCodeProperty = "lang_hashCode_";
  178.  
  179.   /**
  180.    * Adds a lang_hashCode_ field to an object. The hash code is unique for the
  181.    * given object.
  182.    * @param obj {Object} The object to get the hash code for
  183.    * @returns {Number} The hash code for the object
  184.    */
  185.   getHashCode = function(obj) {
  186.     // In IE, DOM nodes do not extend Object so they do not have this method.
  187.     // we need to check hasOwnProperty because the proto might have this set.
  188.     if (obj.hasOwnProperty && obj.hasOwnProperty(hashCodeProperty)) {
  189.       return obj[hashCodeProperty];
  190.     }
  191.     if (!obj[hashCodeProperty]) {
  192.       obj[hashCodeProperty] = ++getHashCode.hashCodeCounter_;
  193.     }
  194.     return obj[hashCodeProperty];
  195.   };
  196.  
  197.   /**
  198.    * Removes the lang_hashCode_ field from an object.
  199.    * @param obj {Object} The object to remove the field from. 
  200.    */
  201.   removeHashCode = function(obj) {
  202.     obj.removeAttribute(hashCodeProperty);
  203.   };
  204.  
  205.   getHashCode.hashCodeCounter_ = 0;
  206. })();
  207.  
  208. /**
  209.  * Fast prefix-checker.
  210.  */
  211. String.prototype.startsWith = function(prefix) {
  212.   if (this.length < prefix.length) {
  213.     return false;
  214.   }
  215.  
  216.   if (this.substring(0, prefix.length) == prefix) {
  217.     return true;
  218.   }
  219.  
  220.   return false;
  221. }
  222.  
  223. /**
  224.  * Removes whitespace from the beginning and end of the string
  225.  */
  226. String.prototype.trim = function() {
  227.   return this.replace(/^\s+|\s+$/g, "");
  228. }
  229.  
  230. /**
  231.  * Does simple python-style string substitution.
  232.  * "foo%s hot%s".subs("bar", "dog") becomes "foobar hotdot".
  233.  * For more fully-featured templating, see template.js.
  234.  */
  235. String.prototype.subs = function() {
  236.   var ret = this;
  237.  
  238.   // this appears to be slow, but testing shows it compares more or less equiv.
  239.   // to the regex.exec method.
  240.   for (var i = 0; i < arguments.length; i++) {
  241.     ret = ret.replace(/\%s/, String(arguments[i]));
  242.   }
  243.  
  244.   return ret;
  245. }
  246.  
  247. /**
  248.  * Returns the last element on an array without removing it.
  249.  */
  250. Array.prototype.peek = function() {
  251.   return this[this.length - 1];
  252. }
  253.  
  254. // TODO(anyone): add splice the first time someone needs it and then implement
  255. // push, pop, shift, unshift in terms of it where possible.
  256.  
  257. // TODO(anyone): add the other neat-o functional methods like map(), etc.
  258.  
  259. /**
  260.  * Partially applies this function to a particular "this object" and zero or
  261.  * more arguments. The result is a new function with some arguments of the first
  262.  * function pre-filled and the value of |this| "pre-specified".
  263.  *
  264.  * Remaining arguments specified at call-time are appended to the pre-
  265.  * specified ones.
  266.  *
  267.  * Also see: partial().
  268.  *
  269.  * Note that bind and partial are optimized such that repeated calls to it do 
  270.  * not create more than one function object, so there is no additional cost for
  271.  * something like:
  272.  *
  273.  * var g = bind(f, obj);
  274.  * var h = partial(g, 1, 2, 3);
  275.  * var k = partial(h, a, b, c);
  276.  *
  277.  * Usage:
  278.  * var barMethBound = bind(myFunction, myObj, "arg1", "arg2");
  279.  * barMethBound("arg3", "arg4");
  280.  *
  281.  * @param thisObj {object} Specifies the object which |this| should point to
  282.  * when the function is run. If the value is null or undefined, it will default
  283.  * to the global object.
  284.  *
  285.  * @returns {function} A partially-applied form of the function bind() was
  286.  * invoked as a method of.
  287.  */
  288. function bind(fn, self, opt_args) {
  289.   var boundargs = (typeof fn.boundArgs_ != "undefined") ? fn.boundArgs_ : [];
  290.   boundargs = boundargs.concat(Array.prototype.slice.call(arguments, 2));
  291.  
  292.   if (typeof fn.boundSelf_ != "undefined") {
  293.     self = fn.boundSelf_;
  294.   }
  295.  
  296.   if (typeof fn.boundFn_ != "undefined") {
  297.     fn = fn.boundFn_;
  298.   }
  299.  
  300.   var newfn = function() {
  301.     // Combine the static args and the new args into one big array
  302.     var args = boundargs.concat(Array.prototype.slice.call(arguments));
  303.     return fn.apply(self, args);
  304.   }
  305.  
  306.   newfn.boundArgs_ = boundargs;
  307.   newfn.boundSelf_ = self;
  308.   newfn.boundFn_ = fn;
  309.  
  310.   return newfn;
  311. }
  312.  
  313. /**
  314.  * An alias to the bind() global function.
  315.  *
  316.  * Usage:
  317.  * var g = f.bind(obj, arg1, arg2);
  318.  * g(arg3, arg4);
  319.  */
  320. Function.prototype.bind = function(self, opt_args) {
  321.   return bind.apply(
  322.     null, [this, self].concat(Array.prototype.slice.call(arguments, 1)));
  323. }
  324.  
  325. /**
  326.  * Like bind(), except that a "this object" is not required. Useful when the
  327.  * target function is already bound.
  328.  * 
  329.  * Usage:
  330.  * var g = partial(f, arg1, arg2);
  331.  * g(arg3, arg4);
  332.  */
  333. function partial(fn, opt_args) {
  334.   return bind.apply(
  335.     null, [fn, null].concat(Array.prototype.slice.call(arguments, 1)));
  336. }
  337.  
  338. /**
  339.  * An alias to the partial() global function.
  340.  *
  341.  * Usage:
  342.  * var g = f.partial(arg1, arg2);
  343.  * g(arg3, arg4);
  344.  */
  345. Function.prototype.partial = function(opt_args) {
  346.   return bind.apply(
  347.     null, [this, null].concat(Array.prototype.slice.call(arguments)));
  348. }
  349.  
  350. /**
  351.  * Convenience. Binds all the methods of obj to itself. Calling this in the
  352.  * constructor before referencing any methods makes things a little more like
  353.  * Java or Python where methods are intrinsically bound to their instance.
  354.  */
  355. function bindMethods(obj) {
  356.   for (var p in obj) {
  357.     if (isFunction(obj[p])) {
  358.       obj[p] = obj[p].bind(obj);
  359.     }
  360.   }
  361. }
  362.  
  363. /**
  364.  * Inherit the prototype methods from one constructor into another.
  365.  *
  366.  * Usage:
  367.  * <pre>
  368.  * function ParentClass(a, b) { }
  369.  * ParentClass.prototype.foo = function(a) { }
  370.  *
  371.  * function ChildClass(a, b, c) {
  372.  *   ParentClass.call(this, a, b);
  373.  * }
  374.  *
  375.  * ChildClass.inherits(ParentClass);
  376.  *
  377.  * var child = new ChildClass("a", "b", "see");
  378.  * child.foo(); // works
  379.  * </pre>
  380.  *
  381.  * In addition, a superclass' implementation of a method can be invoked
  382.  * as follows:
  383.  *
  384.  * <pre>
  385.  * ChildClass.prototype.foo = function(a) {
  386.  *   ChildClass.superClass_.foo.call(this, a);
  387.  *   // other code
  388.  * };
  389.  * </pre>
  390.  */
  391. Function.prototype.inherits = function(parentCtor) {
  392.   var tempCtor = function(){};
  393.   tempCtor.prototype = parentCtor.prototype;
  394.   this.superClass_ = parentCtor.prototype;
  395.   this.prototype = new tempCtor();
  396. }
  397. /* ***** BEGIN LICENSE BLOCK *****
  398.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  399.  *
  400.  * The contents of this file are subject to the Mozilla Public License Version
  401.  * 1.1 (the "License"); you may not use this file except in compliance with
  402.  * the License. You may obtain a copy of the License at
  403.  * http://www.mozilla.org/MPL/
  404.  *
  405.  * Software distributed under the License is distributed on an "AS IS" basis,
  406.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  407.  * for the specific language governing rights and limitations under the
  408.  * License.
  409.  *
  410.  * The Original Code is Google Safe Browsing.
  411.  *
  412.  * The Initial Developer of the Original Code is Google Inc.
  413.  * Portions created by the Initial Developer are Copyright (C) 2006
  414.  * the Initial Developer. All Rights Reserved.
  415.  *
  416.  * Contributor(s):
  417.  *   Fritz Schneider <fritz@google.com> (original author)
  418.  *
  419.  * Alternatively, the contents of this file may be used under the terms of
  420.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  421.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  422.  * in which case the provisions of the GPL or the LGPL are applicable instead
  423.  * of those above. If you wish to allow use of your version of this file only
  424.  * under the terms of either the GPL or the LGPL, and not to allow others to
  425.  * use your version of this file under the terms of the MPL, indicate your
  426.  * decision by deleting the provisions above and replace them with the notice
  427.  * and other provisions required by the GPL or the LGPL. If you do not delete
  428.  * the provisions above, a recipient may use your version of this file under
  429.  * the terms of any one of the MPL, the GPL or the LGPL.
  430.  *
  431.  * ***** END LICENSE BLOCK ***** */
  432.  
  433.  
  434. // This is the code used to interact with data encoded in the
  435. // goog-black-enchash format. The format is basically a map from
  436. // hashed hostnames to encrypted sequences of regular expressions
  437. // where the encryption key is derived from the hashed
  438. // hostname. Encoding lists like this raises the bar slightly on
  439. // deriving complete table data from the db. This data format is NOT
  440. // our idea; we would've raise the bar higher :)
  441. //
  442. // Anyway, this code is a port of the original C++ implementation by
  443. // Garret. To ease verification, I mirrored that code as closely as
  444. // possible.  As a result, you'll see some C++-style variable naming
  445. // and roundabout (C++) ways of doing things. Additionally, I've
  446. // omitted the comments.
  447. //
  448. // This code should not change, except to fix bugs.
  449. //
  450. // TODO: verify that using encodeURI() in getCanonicalHost is OK
  451. // TODO: accommodate other kinds of perl-but-not-javascript qualifiers
  452.  
  453.  
  454. /**
  455.  * This thing knows how to generate lookup keys and decrypt values found in
  456.  * a table of type enchash.
  457.  */
  458. function PROT_EnchashDecrypter() {
  459.   this.debugZone = "enchashdecrypter";
  460.   this.REs_ = PROT_EnchashDecrypter.REs;
  461.   this.hasher_ = new G_CryptoHasher();
  462.   this.base64_ = new G_Base64();
  463.   this.streamCipher_ = Cc["@mozilla.org/security/streamcipher;1"]
  464.                        .createInstance(Ci.nsIStreamCipher);
  465. }
  466.  
  467. PROT_EnchashDecrypter.DATABASE_SALT = "oU3q.72p";
  468. PROT_EnchashDecrypter.SALT_LENGTH = PROT_EnchashDecrypter.DATABASE_SALT.length;
  469.  
  470. PROT_EnchashDecrypter.MAX_DOTS = 5;
  471.  
  472. PROT_EnchashDecrypter.REs = {};
  473. PROT_EnchashDecrypter.REs.FIND_DODGY_CHARS = 
  474.   new RegExp("[\x01-\x1f\x7f-\xff]+");
  475. PROT_EnchashDecrypter.REs.FIND_DODGY_CHARS_GLOBAL = 
  476.   new RegExp("[\x01-\x1f\x7f-\xff]+", "g");
  477. PROT_EnchashDecrypter.REs.FIND_END_DOTS = new RegExp("^\\.+|\\.+$");
  478. PROT_EnchashDecrypter.REs.FIND_END_DOTS_GLOBAL = 
  479.   new RegExp("^\\.+|\\.+$", "g");
  480. PROT_EnchashDecrypter.REs.FIND_MULTIPLE_DOTS = new RegExp("\\.{2,}");
  481. PROT_EnchashDecrypter.REs.FIND_MULTIPLE_DOTS_GLOBAL = 
  482.   new RegExp("\\.{2,}", "g");
  483. PROT_EnchashDecrypter.REs.FIND_TRAILING_DOTS = new RegExp("\\.+$");
  484. PROT_EnchashDecrypter.REs.POSSIBLE_IP = 
  485.   new RegExp("^((?:0x[0-9a-f]+|[0-9\\.])+)$", "i");
  486. PROT_EnchashDecrypter.REs.FIND_BAD_OCTAL = new RegExp("(^|\\.)0\\d*[89]");
  487. PROT_EnchashDecrypter.REs.IS_OCTAL = new RegExp("^0[0-7]*$");
  488. PROT_EnchashDecrypter.REs.IS_DECIMAL = new RegExp("^[0-9]+$");
  489. PROT_EnchashDecrypter.REs.IS_HEX = new RegExp("^0[xX]([0-9a-fA-F]+)$");
  490.  
  491. // Regexps are given in perl regexp format. Unfortunately, JavaScript's
  492. // library isn't completely compatible. For example, you can't specify
  493. // case-insensitive matching by using (?i) in the expression text :(
  494. // So we manually set this bit with the help of this regular expression.
  495. PROT_EnchashDecrypter.REs.CASE_INSENSITIVE = /\(\?i\)/g;
  496.  
  497. /**
  498.  * Helper function 
  499.  *
  500.  * @param str String to get chars from
  501.  * 
  502.  * @param n Number of characters to get
  503.  *
  504.  * @returns String made up of the last n characters of str
  505.  */ 
  506. PROT_EnchashDecrypter.prototype.lastNChars_ = function(str, n) {
  507.   n = -n;
  508.   return str.substr(n);
  509. }
  510.  
  511. /**
  512.  * We have to have our own hex-decoder because decodeURIComponent
  513.  * expects UTF-8 (so it will barf on invalid UTF-8 sequences).
  514.  *
  515.  * @param str String to decode
  516.  * 
  517.  * @returns The decoded string
  518.  */
  519. PROT_EnchashDecrypter.prototype.hexDecode_ = function(str) {
  520.   var output = [];
  521.  
  522.   var i = 0;
  523.   while (i < str.length) {
  524.     var c = str.charAt(i);
  525.   
  526.     if (c == "%" && i + 2 < str.length) {
  527.  
  528.       var asciiVal = Number("0x" + str.charAt(i + 1) + str.charAt(i + 2));
  529.       
  530.       if (!isNaN(asciiVal)) {
  531.         i += 2;
  532.         c = String.fromCharCode(asciiVal);
  533.       }
  534.     }
  535.     
  536.     output[output.length] = c;
  537.     ++i;
  538.   }
  539.   
  540.   return output.join("");
  541. }
  542.  
  543. /**
  544.  * Translate a plaintext enchash value into regular expressions
  545.  *
  546.  * @param data String containing a decrypted enchash db entry
  547.  *
  548.  * @returns An array of RegExps
  549.  */
  550. PROT_EnchashDecrypter.prototype.parseRegExps = function(data) {
  551.   var res = data.split("\t");
  552.   
  553.   G_Debug(this, "Got " + res.length + " regular rexpressions");
  554.   
  555.   for (var i = 0; i < res.length; i++) {
  556.     // Could have leading (?i); if so, set the flag and strip it
  557.     var flags = (this.REs_.CASE_INSENSITIVE.test(res[i])) ? "i" : "";
  558.     res[i] = res[i].replace(this.REs_.CASE_INSENSITIVE, "");
  559.     res[i] = new RegExp(res[i], flags);
  560.   }
  561.  
  562.   return res;
  563. }
  564.  
  565. /**
  566.  * Get the canonical version of the given URL for lookup in a table of 
  567.  * type -url.
  568.  *
  569.  * @param url String to canonicalize
  570.  *
  571.  * @returns String containing the canonicalized url (maximally url-decoded
  572.  *          with hostname normalized, then specially url-encoded)
  573.  */
  574. PROT_EnchashDecrypter.prototype.getCanonicalUrl = function(url) {
  575.   var escapedUrl = PROT_URLCanonicalizer.canonicalizeURL_(url);
  576.   // Normalize the host
  577.   var host = this.getCanonicalHost(escapedUrl);
  578.   if (!host) {
  579.     // Probably an invalid url, return what we have so far.
  580.     return escapedUrl;
  581.   }
  582.  
  583.   // Combine our normalized host with our escaped url.
  584.   var ioService = Cc["@mozilla.org/network/io-service;1"]
  585.                   .getService(Ci.nsIIOService);
  586.   var urlObj = ioService.newURI(escapedUrl, null, null);
  587.   urlObj.host = host;
  588.   return urlObj.asciiSpec;
  589. }
  590.  
  591. /**
  592.  * @param opt_maxDots Number maximum number of dots to include.
  593.  */
  594. PROT_EnchashDecrypter.prototype.getCanonicalHost = function(str, opt_maxDots) {
  595.   var ioService = Cc["@mozilla.org/network/io-service;1"]
  596.                   .getService(Ci.nsIIOService);
  597.   try {
  598.     var urlObj = ioService.newURI(str, null, null);
  599.     var asciiHost = urlObj.asciiHost;
  600.   } catch (e) {
  601.     G_Debug(this, "Unable to get hostname: " + str);
  602.     return "";
  603.   }
  604.  
  605.   var unescaped = this.hexDecode_(asciiHost);
  606.  
  607.   unescaped = unescaped.replace(this.REs_.FIND_DODGY_CHARS_GLOBAL, "")
  608.               .replace(this.REs_.FIND_END_DOTS_GLOBAL, "")
  609.               .replace(this.REs_.FIND_MULTIPLE_DOTS_GLOBAL, ".");
  610.  
  611.   var temp = this.parseIPAddress_(unescaped);
  612.   if (temp)
  613.     unescaped = temp;
  614.  
  615.   // TODO: what, exactly is it supposed to escape? This doesn't esecape 
  616.   // ":", "/", ";", and "?"
  617.   var escaped = encodeURI(unescaped);
  618.  
  619.   if (opt_maxDots) {
  620.     // Limit the number of dots
  621.     var k;
  622.     var index = escaped.length;
  623.     for (k = 0; k < opt_maxDots + 1; k++) {
  624.       temp = escaped.lastIndexOf(".", index - 1);
  625.       if (temp == -1) {
  626.         break;
  627.       } else {
  628.         index = temp;
  629.       }
  630.     }
  631.     
  632.     if (k == opt_maxDots + 1 && index != -1) {
  633.       escaped = escaped.substring(index + 1);
  634.     }
  635.   }
  636.  
  637.   escaped = escaped.toLowerCase();
  638.   return escaped;
  639. }
  640.  
  641. PROT_EnchashDecrypter.prototype.parseIPAddress_ = function(host) {
  642.  
  643.   host = host.replace(this.REs_.FIND_TRAILING_DOTS_GLOBAL, "");
  644.  
  645.   if (!this.REs_.POSSIBLE_IP.test(host))
  646.     return "";
  647.  
  648.   var parts = host.split(".");
  649.   if (parts.length > 4)
  650.     return "";
  651.  
  652.   var allowOctal = !this.REs_.FIND_BAD_OCTAL.test(host);
  653.  
  654.   for (var k = 0; k < parts.length; k++) {
  655.     var canon;
  656.     if (k == parts.length - 1) {
  657.       canon = this.canonicalNum_(parts[k], 5 - parts.length, allowOctal);
  658.     } else {
  659.       canon = this.canonicalNum_(parts[k], 1, allowOctal);
  660.     }
  661.     if (canon != "") 
  662.       parts[k] = canon;
  663.   }
  664.  
  665.   return parts.join(".");
  666. }
  667.  
  668. PROT_EnchashDecrypter.prototype.canonicalNum_ = function(num, bytes, octal) {
  669.   
  670.   if (bytes < 0) 
  671.     return "";
  672.   var temp_num;
  673.  
  674.   if (octal && this.REs_.IS_OCTAL.test(num)) {
  675.  
  676.     num = this.lastNChars_(num, 11);
  677.  
  678.     temp_num = parseInt(num, 8);
  679.     if (isNaN(temp_num))
  680.       temp_num = -1;
  681.  
  682.   } else if (this.REs_.IS_DECIMAL.test(num)) {
  683.  
  684.     num = this.lastNChars_(num, 32);
  685.  
  686.     temp_num = parseInt(num, 10);
  687.     if (isNaN(temp_num))
  688.       temp_num = -1;
  689.  
  690.   } else if (this.REs_.IS_HEX.test(num)) {
  691.  
  692.     num = this.lastNChars_(num, 8);
  693.  
  694.     temp_num = parseInt(num, 16);
  695.     if (isNaN(temp_num))
  696.       temp_num = -1;
  697.  
  698.   } else {
  699.     return "";
  700.   }
  701.  
  702.   if (temp_num == -1) 
  703.     return "";
  704.  
  705.   // Since we mod the number, we're removing the least significant bits.  We
  706.   // Want to push them into the front of the array to preserve the order.
  707.   var parts = [];
  708.   while (bytes--) {
  709.     parts.unshift("" + (temp_num % 256));
  710.     temp_num -= temp_num % 256;
  711.     temp_num /= 256;
  712.   }
  713.  
  714.   return parts.join(".");
  715. }
  716.  
  717. PROT_EnchashDecrypter.prototype.getLookupKey = function(host) {
  718.   var dataKey = PROT_EnchashDecrypter.DATABASE_SALT + host;
  719.   dataKey = this.base64_.arrayifyString(dataKey);
  720.  
  721.   this.hasher_.init(G_CryptoHasher.algorithms.MD5);
  722.   var lookupDigest = this.hasher_.updateFromArray(dataKey);
  723.   var lookupKey = this.hasher_.digestHex();
  724.  
  725.   return lookupKey.toUpperCase();
  726. }
  727.  
  728. PROT_EnchashDecrypter.prototype.decryptData = function(data, host) {
  729.   // XXX: base 64 decoding should be done in C++
  730.   var asciiArray = this.base64_.decodeString(data);
  731.   var ascii = this.base64_.stringifyArray(asciiArray);
  732.  
  733.   var random_salt = ascii.slice(0, PROT_EnchashDecrypter.SALT_LENGTH);
  734.   var encrypted_data = ascii.slice(PROT_EnchashDecrypter.SALT_LENGTH);
  735.   var temp_decryption_key = PROT_EnchashDecrypter.DATABASE_SALT
  736.       + random_salt + host;
  737.   this.hasher_.init(G_CryptoHasher.algorithms.MD5);
  738.   this.hasher_.updateFromString(temp_decryption_key);
  739.  
  740.   var keyFactory = Cc["@mozilla.org/security/keyobjectfactory;1"]
  741.                    .getService(Ci.nsIKeyObjectFactory);
  742.   var key = keyFactory.keyFromString(Ci.nsIKeyObject.RC4,
  743.                                      this.hasher_.digestRaw());
  744.  
  745.   this.streamCipher_.init(key);
  746.   this.streamCipher_.updateFromString(encrypted_data);
  747.  
  748.   return this.streamCipher_.finish(false /* no base64 */);
  749. }
  750.  
  751. /* ***** BEGIN LICENSE BLOCK *****
  752.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  753.  *
  754.  * The contents of this file are subject to the Mozilla Public License Version
  755.  * 1.1 (the "License"); you may not use this file except in compliance with
  756.  * the License. You may obtain a copy of the License at
  757.  * http://www.mozilla.org/MPL/
  758.  *
  759.  * Software distributed under the License is distributed on an "AS IS" basis,
  760.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  761.  * for the specific language governing rights and limitations under the
  762.  * License.
  763.  *
  764.  * The Original Code is Google Safe Browsing.
  765.  *
  766.  * The Initial Developer of the Original Code is Google Inc.
  767.  * Portions created by the Initial Developer are Copyright (C) 2006
  768.  * the Initial Developer. All Rights Reserved.
  769.  *
  770.  * Contributor(s):
  771.  *   Tony Chang <tony@google.com> (original author)
  772.  *
  773.  * Alternatively, the contents of this file may be used under the terms of
  774.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  775.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  776.  * in which case the provisions of the GPL or the LGPL are applicable instead
  777.  * of those above. If you wish to allow use of your version of this file only
  778.  * under the terms of either the GPL or the LGPL, and not to allow others to
  779.  * use your version of this file under the terms of the MPL, indicate your
  780.  * decision by deleting the provisions above and replace them with the notice
  781.  * and other provisions required by the GPL or the LGPL. If you do not delete
  782.  * the provisions above, a recipient may use your version of this file under
  783.  * the terms of any one of the MPL, the GPL or the LGPL.
  784.  *
  785.  * ***** END LICENSE BLOCK ***** */
  786.  
  787. /**
  788.  * This class helps us batch a series of async calls to the db.
  789.  * If any of the tokens is in the database, we fire callback with
  790.  * true as a param.  If all the tokens are not in the  database,
  791.  * we fire callback with false as a param.
  792.  * This is an "Abstract" base class.  Subclasses need to supply
  793.  * the condition_ method.
  794.  *
  795.  * @param tokens Array of strings to lookup in the db
  796.  * @param tableName String name of the table
  797.  * @param callback Function callback function that takes true if the condition
  798.  *        passes.
  799.  */
  800. function MultiQuerier(tokens, tableName, callback) {
  801.   this.tokens_ = tokens;
  802.   this.tableName_ = tableName;
  803.   this.callback_ = callback;
  804.   this.dbservice_ = Cc["@mozilla.org/url-classifier/dbservice;1"]
  805.                     .getService(Ci.nsIUrlClassifierDBService);
  806.   // We put the current token in this variable.
  807.   this.key_ = null;
  808. }
  809.  
  810. /**
  811.  * Run the remaining tokens against the db.
  812.  */
  813. MultiQuerier.prototype.run = function() {
  814.   if (this.tokens_.length == 0) {
  815.     this.callback_.handleEvent(false);
  816.     this.dbservice_ = null;
  817.     this.callback_ = null;
  818.     return;
  819.   }
  820.   
  821.   this.key_ = this.tokens_.pop();
  822.   G_Debug(this, "Looking up " + this.key_ + " in " + this.tableName_);
  823.   this.dbservice_.exists(this.tableName_, this.key_,
  824.                          BindToObject(this.result_, this));
  825. }
  826.  
  827. /**
  828.  * Callback from the db.  If the returned value passes the this.condition_
  829.  * test, go ahead and call the main callback.
  830.  */
  831. MultiQuerier.prototype.result_ = function(value) {
  832.   if (this.condition_(value)) {
  833.     this.callback_.handleEvent(true)
  834.     this.dbservice_ = null;
  835.     this.callback_ = null;
  836.   } else {
  837.     this.run();
  838.   }
  839. }
  840.  
  841. // Subclasses must override this.
  842. MultiQuerier.prototype.condition_ = function(value) {
  843.   throw "MultiQuerier is an abstract base class";
  844. }
  845.  
  846.  
  847. /**
  848.  * Concrete MultiQuerier that stops if the key exists in the db.
  849.  */
  850. function ExistsMultiQuerier(tokens, tableName, callback) {
  851.   MultiQuerier.call(this, tokens, tableName, callback);
  852.   this.debugZone = "existsMultiQuerier";
  853. }
  854. ExistsMultiQuerier.inherits(MultiQuerier);
  855.  
  856. ExistsMultiQuerier.prototype.condition_ = function(value) {
  857.   return value.length > 0;
  858. }
  859.  
  860.  
  861. /**
  862.  * Concrete MultiQuerier that looks up a key, decrypts it, then
  863.  * checks the the resulting regular expressions for a match.
  864.  * @param tokens Array of hosts
  865.  */
  866. function EnchashMultiQuerier(tokens, tableName, callback, url) {
  867.   MultiQuerier.call(this, tokens, tableName, callback);
  868.   this.url_ = url;
  869.   this.enchashDecrypter_ = new PROT_EnchashDecrypter();
  870.   this.debugZone = "enchashMultiQuerier";
  871. }
  872. EnchashMultiQuerier.inherits(MultiQuerier);
  873.  
  874. EnchashMultiQuerier.prototype.run = function() {
  875.   if (this.tokens_.length == 0) {
  876.     this.callback_.handleEvent(false);
  877.     this.dbservice_ = null;
  878.     this.callback_ = null;
  879.     return;
  880.   }
  881.   var host = this.tokens_.pop();
  882.   this.key_ = host;
  883.   var lookupKey = this.enchashDecrypter_.getLookupKey(host);
  884.   this.dbservice_.exists(this.tableName_, lookupKey,
  885.                          BindToObject(this.result_, this));
  886. }
  887.  
  888. EnchashMultiQuerier.prototype.condition_ = function(encryptedValue) {
  889.   if (encryptedValue.length > 0) {
  890.     // We have encrypted regular expressions for this host. Let's 
  891.     // decrypt them and see if we have a match.
  892.     var decrypted = this.enchashDecrypter_.decryptData(encryptedValue,
  893.                                                        this.key_);
  894.     var res = this.enchashDecrypter_.parseRegExps(decrypted);
  895.     for (var j = 0; j < res.length; j++) {
  896.       if (res[j].test(this.url_)) {
  897.         return true;
  898.       }
  899.     }
  900.   }
  901.   return false;
  902. }
  903. /* ***** BEGIN LICENSE BLOCK *****
  904.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  905.  *
  906.  * The contents of this file are subject to the Mozilla Public License Version
  907.  * 1.1 (the "License"); you may not use this file except in compliance with
  908.  * the License. You may obtain a copy of the License at
  909.  * http://www.mozilla.org/MPL/
  910.  *
  911.  * Software distributed under the License is distributed on an "AS IS" basis,
  912.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  913.  * for the specific language governing rights and limitations under the
  914.  * License.
  915.  *
  916.  * The Original Code is Google Safe Browsing.
  917.  *
  918.  * The Initial Developer of the Original Code is Google Inc.
  919.  * Portions created by the Initial Developer are Copyright (C) 2006
  920.  * the Initial Developer. All Rights Reserved.
  921.  *
  922.  * Contributor(s):
  923.  *   Fritz Schneider <fritz@google.com> (original author)
  924.  *
  925.  * Alternatively, the contents of this file may be used under the terms of
  926.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  927.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  928.  * in which case the provisions of the GPL or the LGPL are applicable instead
  929.  * of those above. If you wish to allow use of your version of this file only
  930.  * under the terms of either the GPL or the LGPL, and not to allow others to
  931.  * use your version of this file under the terms of the MPL, indicate your
  932.  * decision by deleting the provisions above and replace them with the notice
  933.  * and other provisions required by the GPL or the LGPL. If you do not delete
  934.  * the provisions above, a recipient may use your version of this file under
  935.  * the terms of any one of the MPL, the GPL or the LGPL.
  936.  *
  937.  * ***** END LICENSE BLOCK ***** */
  938.  
  939.  
  940. // This is the class we use to canonicalize URLs for TRTables of type
  941. // url.  We maximally URL-decode the URL, treating +'s as if they're
  942. // not special.  We then specially URL-encode it (we encode ASCII
  943. // values [0, 32] (whitespace or unprintable), 37 (%), [127, 255]
  944. // (unprintable)).  
  945. //
  946. // This mapping is not a function. That is, multiple URLs can map to
  947. // the same canonical representation. However this is OK because
  948. // collisions happen only when there are weird characters (e.g.,
  949. // nonprintables), and the canonical representation makes us robust
  950. // to some weird kinds of encoding we could see. 
  951. //
  952. // All members are static at this point -- this is basically a namespace.
  953.  
  954.  
  955. /**
  956.  * Create a new URLCanonicalizer. Useless because members are static.
  957.  *
  958.  * @constructor
  959.  */
  960. function PROT_URLCanonicalizer() { 
  961.   throw new Error("No need to instantiate a canonicalizer at this point.");
  962. }
  963.  
  964. PROT_URLCanonicalizer.debugZone = "urlcanonicalizer";
  965.  
  966. PROT_URLCanonicalizer.hexChars_ = "0123456789ABCDEF";
  967.  
  968. /**
  969.  * Helper funciton to (maybe) convert a two-character hex string into its 
  970.  * decimal numerical equivalent
  971.  *
  972.  * @param hh String of length two that might be a valid hex sequence
  973.  *
  974.  * @returns Number: NaN if hh wasn't valid hex, else the appropriate decimal
  975.  *          value
  976.  */
  977. PROT_URLCanonicalizer.hexPairToInt_ = function(hh) {
  978.   return Number("0x" + hh);
  979. }
  980.  
  981. /**
  982.  * Helper function to hex-encode a number
  983.  *
  984.  * @param val Number in range [0, 255]
  985.  *
  986.  * @returns String containing the hex representation of that number (sans 0x)
  987.  */
  988. PROT_URLCanonicalizer.toHex_ = function(val) {
  989.   var retVal = PROT_URLCanonicalizer.hexChars_.charAt((val >> 4) & 15) + 
  990.                PROT_URLCanonicalizer.hexChars_.charAt(val & 15);
  991.   return retVal;
  992. }
  993.  
  994. /**
  995.  * Canonicalize a URL.  DON'T USE THIS DIRECTLY.  Use
  996.  * PROT_EnchashDecrypter.prototype.getCanonicalUrl instead.  This method
  997.  * url-decodes a string, but it doesn't normalize the hostname.  The method
  998.  * in EnchashDecrypter first calls this method, then normalizes the hostname.
  999.  *
  1000.  * @param url String to canonicalize
  1001.  *
  1002.  * @returns String containing the canonicalized url (maximally url-decoded,
  1003.  *          then specially url-encoded)
  1004.  */
  1005. PROT_URLCanonicalizer.canonicalizeURL_ = function(url) {
  1006.   var arrayOfASCIIVals = PROT_URLCanonicalizer.fullyDecodeURL_(url);
  1007.   return PROT_URLCanonicalizer.specialEncodeURL_(arrayOfASCIIVals);
  1008. }
  1009.  
  1010. /**
  1011.  * Maximally URL-decode a URL. This breaks the semantics of the URL, but
  1012.  * we don't care because we're using it for lookup, not for navigation.
  1013.  * We break multi-byte UTF-8 escape sequences as well, but we don't care
  1014.  * so long as they canonicalize the same way consistently (they do).
  1015.  *
  1016.  * @param url String containing the URL to maximally decode. Should ONLY
  1017.  *            contain characters with UCS codepoints U+0001 to U+00FF
  1018.  *            (the ASCII set minus null).
  1019.  *
  1020.  * @returns Array of ASCII values corresponding to the decoded sequence of
  1021.  *          characters in the url
  1022.  */
  1023. PROT_URLCanonicalizer.fullyDecodeURL_ = function(url) {
  1024.  
  1025.   // The goals here are: simplicity, correctness, and most of all
  1026.   // portability; we want the same implementation of canonicalization
  1027.   // wherever we use it so as to to minimize the chances of
  1028.   // inconsistency. For example, we have to do this canonicalization
  1029.   // on URLs we get from third parties, and at the lookup server when 
  1030.   // we get a request.
  1031.   //
  1032.   // The following implementation should translate easily to any
  1033.   // language that supports arrays and pointers or references. Note
  1034.   // that arrays are pointer types in JavaScript, so foo = [some,
  1035.   // array] points foo at the array; it doesn't copy it. The
  1036.   // implementation is efficient (linear) so long as most %'s in the
  1037.   // url belong to valid escape sequences and there aren't too many
  1038.   // doubly-escaped values.
  1039.  
  1040.   // The basic idea is to copy current input to output, decoding escape 
  1041.   // sequences as we see them, until we decode a %. At that point we start
  1042.   // copying into the "next iteration buffer" instead of the output buffer; 
  1043.   // we do this so we can accomodate multiply-escaped strings. When we hit 
  1044.   // the end of the input, we take the "next iteration buffer" as our input,
  1045.   // and start over.
  1046.  
  1047.   var nextIteration = url.split("");
  1048.   var output = [];
  1049.  
  1050.   while (nextIteration.length) {
  1051.  
  1052.     var decodedAPercent = false;
  1053.     var thisIteration = nextIteration;
  1054.     var nextIteration = [];
  1055.     
  1056.     var i = 0;
  1057.     while (i < thisIteration.length) {
  1058.  
  1059.       var c = thisIteration[i];
  1060.       if (c == "%" && i + 2 < thisIteration.length) {
  1061.  
  1062.         // Peek ahead to see if we have a valid HH sequence
  1063.         var asciiVal = 
  1064.           PROT_URLCanonicalizer.hexPairToInt_(thisIteration[i + 1] + 
  1065.                                               thisIteration[i + 2]);
  1066.         if (!isNaN(asciiVal)) {
  1067.           i += 2;                   // Valid HH sequence; consume it
  1068.           
  1069.           if (asciiVal == 0)        // We special case nulls
  1070.             asciiVal = 1;
  1071.           
  1072.           c = String.fromCharCode(asciiVal);
  1073.           if (c == "%")
  1074.             decodedAPercent = true;
  1075.         }
  1076.       }
  1077.  
  1078.       if (decodedAPercent)
  1079.         nextIteration[nextIteration.length] = c;
  1080.       else
  1081.         output[output.length] = c.charCodeAt(0);
  1082.       
  1083.       ++i;
  1084.     }
  1085.   }
  1086.  
  1087.   return output;
  1088. }
  1089.  
  1090. /**
  1091.  * Maximally URL-decode a URL (same as fullyDecodeURL_ except that it 
  1092.  * returns a string). Useful for making unittests more readable.
  1093.  *
  1094.  * @param url String containing the URL to maximally decode. Should ONLY
  1095.  *            contain characters with UCS codepoints U+0001 to U+00FF
  1096.  *            (the ASCII set minus null).
  1097.  *
  1098.  * @returns String containing the decoded URL
  1099.  */
  1100. PROT_URLCanonicalizer.fullyDecodeURLAsString_ = function(url) {
  1101.   var arrayOfASCIIVals = PROT_URLCanonicalizer.fullyDecodeURL_(url);
  1102.   var s = "";
  1103.   for (var i = 0; i < arrayOfASCIIVals.length; i++)
  1104.     s += String.fromCharCode(arrayOfASCIIVals[i]);
  1105.   return s;
  1106. }
  1107.  
  1108. /**
  1109.  * Specially URL-encode the given array of ASCII values. We want to encode 
  1110.  * the charcters: [0, 32], 37, [127, 255].
  1111.  *
  1112.  * @param arrayOfASCIIValues Array of ascii values (numbers) to encode
  1113.  *
  1114.  * @returns String corresonding to the escaped URL
  1115.  */
  1116. PROT_URLCanonicalizer.specialEncodeURL_ = function(arrayOfASCIIValues) {
  1117.  
  1118.   var output = [];
  1119.   for (var i = 0; i < arrayOfASCIIValues.length; i++) {
  1120.     var n = arrayOfASCIIValues[i];
  1121.  
  1122.     if (n <= 32 || n == 37 || n >= 127)
  1123.       output.push("%" + ((!n) ? "01" : PROT_URLCanonicalizer.toHex_(n)));
  1124.     else
  1125.       output.push(String.fromCharCode(n));
  1126.   }
  1127.  
  1128.   return output.join("");
  1129. }
  1130.  
  1131.  
  1132. /* ***** BEGIN LICENSE BLOCK *****
  1133.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  1134.  *
  1135.  * The contents of this file are subject to the Mozilla Public License Version
  1136.  * 1.1 (the "License"); you may not use this file except in compliance with
  1137.  * the License. You may obtain a copy of the License at
  1138.  * http://www.mozilla.org/MPL/
  1139.  *
  1140.  * Software distributed under the License is distributed on an "AS IS" basis,
  1141.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  1142.  * for the specific language governing rights and limitations under the
  1143.  * License.
  1144.  *
  1145.  * The Original Code is Url Classifier code
  1146.  *
  1147.  * The Initial Developer of the Original Code is
  1148.  * Google Inc.
  1149.  * Portions created by the Initial Developer are Copyright (C) 2006
  1150.  * the Initial Developer. All Rights Reserved.
  1151.  *
  1152.  * Contributor(s):
  1153.  *   Tony Chang <tony@ponderer.org>
  1154.  *
  1155.  * Alternatively, the contents of this file may be used under the terms of
  1156.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  1157.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  1158.  * in which case the provisions of the GPL or the LGPL are applicable instead
  1159.  * of those above. If you wish to allow use of your version of this file only
  1160.  * under the terms of either the GPL or the LGPL, and not to allow others to
  1161.  * use your version of this file under the terms of the MPL, indicate your
  1162.  * decision by deleting the provisions above and replace them with the notice
  1163.  * and other provisions required by the GPL or the LGPL. If you do not delete
  1164.  * the provisions above, a recipient may use your version of this file under
  1165.  * the terms of any one of the MPL, the GPL or the LGPL.
  1166.  *
  1167.  * ***** END LICENSE BLOCK ***** */
  1168.  
  1169. // XXX: This should all be moved into the dbservice class so it happens
  1170. // in the background thread.
  1171.  
  1172. /**
  1173.  * Abstract base class for a lookup table.
  1174.  * @construction
  1175.  */
  1176. function UrlClassifierTable() {
  1177.   this.debugZone = "urlclassifier-table";
  1178.   this.name = '';
  1179.   this.needsUpdate = false;
  1180.   this.enchashDecrypter_ = new PROT_EnchashDecrypter();
  1181. }
  1182.  
  1183. UrlClassifierTable.prototype.QueryInterface = function(iid) {
  1184.   if (iid.equals(Components.interfaces.nsISupports) ||
  1185.       iid.equals(Components.interfaces.nsIUrlClassifierTable))
  1186.     return this;                                              
  1187.   Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
  1188.   return null;
  1189. }
  1190.  
  1191. /**
  1192.  * Subclasses need to implment this method.
  1193.  */
  1194. UrlClassifierTable.prototype.exists = function(url, callback) {
  1195.   throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  1196. }
  1197.  
  1198. /////////////////////////////////////////////////////////////////////
  1199. // Url table implementation
  1200. function UrlClassifierTableUrl() {
  1201.   UrlClassifierTable.call(this);
  1202. }
  1203. UrlClassifierTableUrl.inherits(UrlClassifierTable);
  1204.  
  1205. /**
  1206.  * Look up a URL in a URL table
  1207.  */
  1208. UrlClassifierTableUrl.prototype.exists = function(url, callback) {
  1209.   // PROT_URLCanonicalizer.canonicalizeURL_ is the old way of canonicalizing a
  1210.   // URL.  Unfortunately, it doesn't normalize numeric domains so alternate IP
  1211.   // formats (hex, octal, etc) won't trigger a match.
  1212.   // this.enchashDecrypter_.getCanonicalUrl does the right thing and
  1213.   // normalizes a URL to 4 decimal numbers, but the update server may still be
  1214.   // giving us encoded IP addresses.  So to be safe, we check both cases.
  1215.   var oldCanonicalized = PROT_URLCanonicalizer.canonicalizeURL_(url);
  1216.   var canonicalized = this.enchashDecrypter_.getCanonicalUrl(url);
  1217.   G_Debug(this, "Looking up: " + url + " (" + oldCanonicalized + " and " +
  1218.                 canonicalized + ")");
  1219.   (new ExistsMultiQuerier([oldCanonicalized, canonicalized],
  1220.                           this.name,
  1221.                           callback)).run();
  1222. }
  1223.  
  1224. /////////////////////////////////////////////////////////////////////
  1225. // Domain table implementation
  1226.  
  1227. function UrlClassifierTableDomain() {
  1228.   UrlClassifierTable.call(this);
  1229.   this.debugZone = "urlclassifier-table-domain";
  1230.   this.ioService_ = Cc["@mozilla.org/network/io-service;1"]
  1231.                     .getService(Ci.nsIIOService);
  1232. }
  1233. UrlClassifierTableDomain.inherits(UrlClassifierTable);
  1234.  
  1235. /**
  1236.  * Look up a URL in a domain table
  1237.  * We also try to lookup domain + first path component (e.g.,
  1238.  * www.mozilla.org/products).
  1239.  *
  1240.  * @returns Boolean true if the url domain is in the table
  1241.  */
  1242. UrlClassifierTableDomain.prototype.exists = function(url, callback) {
  1243.   var canonicalized = this.enchashDecrypter_.getCanonicalUrl(url);
  1244.   var urlObj = this.ioService_.newURI(canonicalized, null, null);
  1245.   var host = '';
  1246.   try {
  1247.     host = urlObj.host;
  1248.   } catch (e) { }
  1249.   var hostComponents = host.split(".");
  1250.  
  1251.   // Try to get the path of the URL.  Pseudo urls (like wyciwyg:) throw
  1252.   // errors when trying to convert to an nsIURL so we wrap in a try/catch
  1253.   // block.
  1254.   var path = ""
  1255.   try {
  1256.     urlObj.QueryInterface(Ci.nsIURL);
  1257.     path = urlObj.filePath;
  1258.   } catch (e) { }
  1259.  
  1260.   var pathComponents = path.split("/");
  1261.  
  1262.   // We don't have a good way map from hosts to domains, so we instead try
  1263.   // each possibility. Could probably optimize to start at the second dot?
  1264.   var possible = [];
  1265.   for (var i = 0; i < hostComponents.length - 1; i++) {
  1266.     host = hostComponents.slice(i).join(".");
  1267.     possible.push(host);
  1268.  
  1269.     // The path starts with a "/", so we are interested in the second path
  1270.     // component if it is available
  1271.     if (pathComponents.length >= 2 && pathComponents[1].length > 0) {
  1272.       host = host + "/" + pathComponents[1];
  1273.       possible.push(host);
  1274.     }
  1275.   }
  1276.  
  1277.   // Run the possible domains against the db.
  1278.   (new ExistsMultiQuerier(possible, this.name, callback)).run();
  1279. }
  1280.  
  1281. /////////////////////////////////////////////////////////////////////
  1282. // Enchash table implementation
  1283.  
  1284. function UrlClassifierTableEnchash() {
  1285.   UrlClassifierTable.call(this);
  1286.   this.debugZone = "urlclassifier-table-enchash";
  1287. }
  1288. UrlClassifierTableEnchash.inherits(UrlClassifierTable);
  1289.  
  1290. /**
  1291.  * Look up a URL in an enchashDB.  We try all sub domains (up to MAX_DOTS).
  1292.  */
  1293. UrlClassifierTableEnchash.prototype.exists = function(url, callback) {
  1294.   url = this.enchashDecrypter_.getCanonicalUrl(url);
  1295.   var host = this.enchashDecrypter_.getCanonicalHost(url,
  1296.                                                PROT_EnchashDecrypter.MAX_DOTS);
  1297.  
  1298.   var possible = [];
  1299.   for (var i = 0; i < PROT_EnchashDecrypter.MAX_DOTS + 1; i++) {
  1300.     possible.push(host);
  1301.  
  1302.     var index = host.indexOf(".");
  1303.     if (index == -1)
  1304.       break;
  1305.     host = host.substring(index + 1);
  1306.   }
  1307.   // Run the possible domains against the db.
  1308.   (new EnchashMultiQuerier(possible, this.name, callback, url)).run();
  1309. }
  1310. //@line 47 "/build/buildd/firefox-2.0.0.3+1/toolkit/components/url-classifier/src/nsUrlClassifierTable.js"
  1311.  
  1312. var modScope = this;
  1313. function Init() {
  1314.   // Pull the library in.
  1315.   var jslib = Cc["@mozilla.org/url-classifier/jslib;1"]
  1316.               .getService().wrappedJSObject;
  1317.   modScope.G_Preferences = jslib.G_Preferences;
  1318.   modScope.G_PreferenceObserver = jslib.G_PreferenceObserver;
  1319.   modScope.G_Debug = jslib.G_Debug;
  1320.   modScope.G_CryptoHasher = jslib.G_CryptoHasher;
  1321.   modScope.G_Base64 = jslib.G_Base64;
  1322.   modScope.BindToObject = jslib.BindToObject;
  1323.  
  1324.   // We only need to call Init once.
  1325.   modScope.Init = function() {};
  1326. }
  1327.  
  1328.  
  1329. function UrlClassifierTableMod() {
  1330.   this.components = {};
  1331.   this.addComponent({
  1332.       cid: "{43399ee0-da0b-46a8-9541-08721265981c}",
  1333.       name: "UrlClassifier Table Url Module",
  1334.       progid: "@mozilla.org/url-classifier/table;1?type=url",
  1335.       factory: new UrlClassifierTableFactory(UrlClassifierTableUrl)
  1336.     });
  1337.   this.addComponent({
  1338.       cid: "{3b5004c6-3fcd-4b12-b311-a4dfbeaf27aa}",
  1339.       name: "UrlClassifier Table Domain Module",
  1340.       progid: "@mozilla.org/url-classifier/table;1?type=domain",
  1341.       factory: new UrlClassifierTableFactory(UrlClassifierTableDomain)
  1342.     });
  1343.   this.addComponent({
  1344.       cid: "{04f15d1d-2db8-4b8e-91d7-82f30308b434}",
  1345.       name: "UrlClassifier Table Enchash Module",
  1346.       progid: "@mozilla.org/url-classifier/table;1?type=enchash",
  1347.       factory: new UrlClassifierTableFactory(UrlClassifierTableEnchash)
  1348.     });
  1349. }
  1350.  
  1351. UrlClassifierTableMod.prototype.addComponent = function(comp) {
  1352.   this.components[comp.cid] = comp;
  1353. };
  1354.  
  1355. UrlClassifierTableMod.prototype.registerSelf = function(compMgr, fileSpec, loc, type) {
  1356.   compMgr = compMgr.QueryInterface(Ci.nsIComponentRegistrar);
  1357.   // Register all the components
  1358.   for (var cid in this.components) {
  1359.     var comp = this.components[cid];
  1360.     compMgr.registerFactoryLocation(Components.ID(comp.cid),
  1361.                                     comp.name,
  1362.                                     comp.progid,
  1363.                                     fileSpec,
  1364.                                     loc,
  1365.                                     type);
  1366.   }
  1367. };
  1368.  
  1369. UrlClassifierTableMod.prototype.getClassObject = function(compMgr, cid, iid) {
  1370.   var comp = this.components[cid.toString()];
  1371.  
  1372.   if (!comp)
  1373.     throw Components.results.NS_ERROR_NO_INTERFACE;
  1374.   if (!iid.equals(Ci.nsIFactory))
  1375.     throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  1376.  
  1377.   return comp.factory;
  1378. };
  1379.  
  1380. UrlClassifierTableMod.prototype.canUnload = function(compMgr) {
  1381.   return true;
  1382. };
  1383.  
  1384. /**
  1385.  * Create a factory.
  1386.  * @param ctor Function constructor for the object we're creating.
  1387.  */
  1388. function UrlClassifierTableFactory(ctor) {
  1389.   this.ctor = ctor;
  1390. }
  1391.  
  1392. UrlClassifierTableFactory.prototype.createInstance = function(outer, iid) {
  1393.   if (outer != null)
  1394.     throw Components.results.NS_ERROR_NO_AGGREGATION;
  1395.   Init();
  1396.   return (new this.ctor()).QueryInterface(iid);
  1397. };
  1398.  
  1399. var modInst = new UrlClassifierTableMod();
  1400.  
  1401. function NSGetModule(compMgr, fileSpec) {
  1402.   return modInst;
  1403. }
  1404.